<p>Successful Zip Bomb attacks occur when an application expands untrusted archive files without controlling the size of the expanded data, which can
lead to denial of service. A Zip bomb is usually a malicious archive file of a few kilobytes of compressed data but turned into gigabytes of
uncompressed data. To achieve this extreme <a href="https://en.wikipedia.org/wiki/Data_compression_ratio">compression ratio</a>, attackers will
compress irrelevant data (eg: a long string of repeated bytes).</p>
<h2>Ask Yourself Whether</h2>
<p>Archives to expand are untrusted and:</p>
<ul>
  <li> There is no validation of the number of entries in the archive. </li>
  <li> There is no validation of the total size of the uncompressed data. </li>
  <li> There is no validation of the ratio between the compressed and uncompressed archive entry. </li>
</ul>
<p>There is a risk if you answered yes to any of those questions.</p>
<h2>Recommended Secure Coding Practices</h2>
<ul>
  <li> Define and control the ratio between compressed and uncompressed data, in general the data compression ratio for most of the legit archives is
  1 to 3. </li>
  <li> Define and control the threshold for maximum total size of the uncompressed data. </li>
  <li> Count the number of file entries extracted from the archive and abort the extraction if their number is greater than a predefined threshold, in
  particular it’s not recommended to recursively expand archives (an entry of an archive could be also an archive). </li>
</ul>
<h2>Sensitive Code Example</h2>
<pre>
using var zipToOpen = new FileStream(@"ZipBomb.zip", FileMode.Open);
using var archive = new ZipArchive(zipToOpen, ZipArchiveMode.Read);
foreach (ZipArchiveEntry entry in archive.Entries)
{
  entry.ExtractToFile("./output_onlyfortesting.txt", true); // Sensitive
}
</pre>
<h2>Compliant Solution</h2>
<pre>
int THRESHOLD_ENTRIES = 10000;
int THRESHOLD_SIZE = 1000000000; // 1 GB
double THRESHOLD_RATIO = 10;
int totalSizeArchive = 0;
int totalEntryArchive = 0;

using var zipToOpen = new FileStream(@"ZipBomb.zip", FileMode.Open);
using var archive = new ZipArchive(zipToOpen, ZipArchiveMode.Read);
foreach (ZipArchiveEntry entry in archive.Entries)
{
  totalEntryArchive ++;

  using (Stream st = entry.Open())
  {
    byte[] buffer = new byte[1024];
    int totalSizeEntry = 0;
    int numBytesRead = 0;

    do
    {
      numBytesRead = st.Read(buffer, 0, 1024);
      totalSizeEntry += numBytesRead;
      totalSizeArchive += numBytesRead;
      double compressionRatio = totalSizeEntry / entry.CompressedLength;

      if(compressionRatio &gt; THRESHOLD_RATIO) {
        // ratio between compressed and uncompressed data is highly suspicious, looks like a Zip Bomb Attack
        break;
      }
    }
    while (numBytesRead &gt; 0);
  }

  if(totalSizeArchive &gt; THRESHOLD_SIZE) {
      // the uncompressed data size is too much for the application resource capacity
      break;
  }

  if(totalEntryArchive &gt; THRESHOLD_ENTRIES) {
      // too much entries in this archive, can lead to inodes exhaustion of the system
      break;
  }
}
</pre>
<h2>See</h2>
<ul>
  <li> OWASP - <a href="https://owasp.org/Top10/A01_2021-Broken_Access_Control/">Top 10 2021 Category A1 - Broken Access Control</a> </li>
  <li> OWASP - <a href="https://owasp.org/Top10/A05_2021-Security_Misconfiguration/">Top 10 2021 Category A5 - Security Misconfiguration</a> </li>
  <li> OWASP - <a href="https://owasp.org/www-project-top-ten/2017/A5_2017-Broken_Access_Control">Top 10 2017 Category A5 - Broken Access Control</a>
  </li>
  <li> OWASP - <a href="https://owasp.org/www-project-top-ten/2017/A6_2017-Security_Misconfiguration">Top 10 2017 Category A6 - Security
  Misconfiguration</a> </li>
  <li> CWE - <a href="https://cwe.mitre.org/data/definitions/409">CWE-409 - Improper Handling of Highly Compressed Data (Data Amplification)</a> </li>
  <li> <a href="https://www.bamsoftware.com/hacks/zipbomb/">bamsoftware.com</a> - A better Zip Bomb </li>
</ul>

